// 实现这个项目的构建任务
const { src, dest, parallel, series, watch } = require('gulp')
const del = require('del');
const browserSync = require('browser-sync')//开发服务器，支持热更新
const sass = require('gulp-sass')
const loadPlugins = require('gulp-load-plugins')//加载全部插件
const GulpSSH = require('gulp-ssh')


const plugins = loadPlugins()
const bs = browserSync.create()//创建服务器

const data = {
    menus: [
      {
        name: 'Home',
        icon: 'aperture',
        link: 'index.html'
      },
      {
        name: 'Features',
        link: 'features.html'
      },
      {
        name: 'About',
        link: 'about.html'
      },
      {
        name: 'Contact',
        link: '#',
        children: [
          {
            name: 'Twitter',
            link: 'https://twitter.com/w_zce'
          },
          {
            name: 'About',
            link: 'https://weibo.com/zceme'
          },
          {
            name: 'divider'
          },
          {
            name: 'About',
            link: 'https://github.com/zce'
          }
        ]
      }
    ],
    pkg: require('./package.json'),
    date: new Date()
}


//清空目录
const clean = () => {
    return del(['dist', 'temp'])
}

const lint = () => {
    return src('src/assets/scripts/*.js', { base: 'src' })
    .pipe(plugins.eslint())
    .pipe(plugins.eslint.format())
    .pipe(plugins.eslint.failAfterError());
}

const style = () => {
    return src('src/assets/styles/*.scss', { base: 'src' })//base：基准路径，用于保留src后面的原有目录结构
    .pipe(sass({ outputStyle: 'expanded' }))//expanded用于生成的样式文件结束括号在新行
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true }))//热更新：以流的的方式往浏览器退
}
const script = () => {
    return src('src/assets/scripts/*.js', { base: 'src' })
    .pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true }))
}
  
const page = () => {
    return src('src/*.html', { base: 'src' })
    .pipe(plugins.swig({ data, defaults: { cache: false } })) //data传递所需数据，cache 防止模板缓存导致页面不能及时更新
    .pipe(dest('temp'))
    .pipe(bs.reload({ stream: true }))
}
//编译文件
const compile = parallel(style, script, page)

const image = () => {//不需要放到temp，只有影响userref的才放到temp
    return src('src/assets/images/**', { base: 'src' })
      .pipe(plugins.imagemin())
      .pipe(dest('dist'))
}
  
const font = () => {
    return src('src/assets/fonts/**', { base: 'src' })
    .pipe(plugins.imagemin())
    .pipe(dest('dist'))
}
  
const extra = () => {//其他类型文件直接拷贝
    return src('public/**', { base: 'public' })
    .pipe(dest('dist'))
}

//本地服务
const devServe = () => {//热更新开发服务器
    //监视源代码变化，文件变化执行任务
    watch('src/assets/styles/*.scss', style)
    watch('src/assets/scripts/*.js', script)
    watch('src/*.html', page)
    watch([//src下文件字体及publish变化时浏览器更新
      'src/assets/images/**',
      'src/assets/fonts/**',
      'public/**'
    ], bs.reload)
  
    bs.init({//初始化服务器相关配置
      notify: false,//不提示
      port: 2080,//指定端口
      server: {
        baseDir: ['temp', 'src', 'public'],//指定网站根目录，先找第一个元素对应的目录，再依次往后找，
        //在开发阶段，请求图片请求dist和src没有区别，由于compile没有处理图片字体任务，dist下面找不到图片，直接去找src下面的图片
        routes: {//配置路由映射，仅用于开发环境，优先于baseDir
          '/node_modules': 'node_modules'//把/node_modules请求指向node_modules目录
        }
      }
    })
}

const serve = series(compile, devServe)


//防止读写冲突，引入临时目录temp，编译的代码先放入temp，useref处理后最后再放入dist
const useref = () => {//处理引用关系，自动处理构建注释,把同一注释间内容合并至同一个文件中
    return src('temp/*.html', { base: 'temp' })//找生成文件中的htnl中的引用关系
    .pipe(plugins.useref({ searchPath: ['temp', '.'] }))//引用的文件所在的目录，先找dist下的assets/css等，再找./node_moldules的css
    // html js css
    .pipe(plugins.if(/\.js$/, plugins.uglify()))
    .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
    .pipe(plugins.if(/\.html$/, plugins.htmlmin({
    collapseWhitespace: true,//换行符删除
    minifyCSS: true,//行内样式压缩
    minifyJS: true//行内代码压缩
    })))
    .pipe(dest('dist'))
}

const build =  series(
    clean,
    parallel(
      series(compile, useref),
      image,
      font,
      extra
    )
)

const processArgs = process.argv;
const isProduct = processArgs[processArgs.length - 1 ] === '--production'
const remotePath = `/home/web/test`;
const config = {
    ssh: { 
        host: isProduct ? '' : '192.160.0.108',
        port: isProduct ? 22 : 8822,
        username: 'root',
        password: isProduct ? '' : '12321312',
    },
    remotePath,
    commands: [
        // 删除现有文件
        `rm -rf ${remotePath}`,
    ],
}
const gulpSSH = new GulpSSH({
    ignoreErrors: false,
    sshConfig: config.ssh,
})
const execSSH = () => {
    return gulpSSH.shell(config.commands, { filePath: 'commands.log' })
    .pipe(dest('logs'))
}

const pushSSH = () => {
    src('dist/**')
    .pipe(gulpSSH.dest(config.remotePath))
}

const deploy = series(execSSH, pushSSH)
module.exports = {
    clean,
    lint,  
    serve,
    start: compile,
    build,
    deploy
}